home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 098 / curses.arc / TC.C < prev   
Text File  |  1985-07-08  |  41KB  |  1,590 lines

  1. #include <stdio.h>
  2. #include <dos.h>
  3. #include <fcntl.h>
  4. #include <ctype.h>
  5. #include "scr.h"
  6. #define NROWS 24
  7. #define BAD -1
  8. #define GOOD 1
  9. #define NCOLS  80
  10. #define true 1
  11. #define false 0
  12. #define rom_call 0x10
  13. #define HILIT_ON        8
  14. #define BLINK           128             /* may be 176 */
  15. #define REVERSE         0x70
  16. #define NORMAL 7
  17. #define HIGHLIGHT 15
  18. #define BHIGHLIGHT 184
  19. #define UNDERLINE 1
  20. #define alpha 'A'
  21. #define ucase 'U'
  22. #define numeric 'N'
  23. #define floatting 'F'
  24. #define date 'D'
  25. #define telephone 'T'
  26. #define invisible 'I'
  27. #define soc_sec 'S'
  28. #define reg 'R'
  29. #define nothing 0
  30. #define dec_point 229         /* representation of decimal point */
  31. #define clear()         (wclear(stdscr))
  32. #define move(c, c1)     (wmove(stdscr, c, c1))
  33. #define delch()         (wdelch(stdscr))
  34. #define deleteln()      (wdeleteln(stdscr))
  35. #define addch(c)        (waddch(stdscr, c))
  36. #define clrtoeol()      (wclrtoeol(stdscr))
  37. #define clrtobot()      (wclrtobot(stdscr))
  38. #define insertln()      (winsertln(stdscr))
  39. #define insch(c)        (winsch(stdscr, c))
  40. #define inch()          (winch(stdscr))
  41. #define standout()      (wstandout(stdscr))
  42. #define standend()      (wstandend(stdscr))
  43. #define scroll()        (wscroll(stdscr))
  44. #define echo()          (0)
  45. #define noecho()        (0)
  46. #define nl()            (0)
  47. #define nonl()          (0)
  48. #define addstr(c)       (waddstr(stdscr, c))
  49. #define refresh()       (wrefresh(stdscr))
  50. #define mvprint(r, c, s)  move(r,c); addstr(s); refresh()
  51. #define mvclear(r, c)   move(r, c); clrtoeol(); refresh()
  52.  
  53. char *malloc(), *scr_buff, *strcat(), *strupr(), *strchr();
  54. char *lf = "\n", *lf_cr = "\n\r";
  55.  
  56. int nkey, key_code[100][5], retrace = true;
  57. int page_size, line_size, user_page, printer;
  58. int mcv();
  59.  
  60. typedef struct win_struct {
  61.         int row_org, col_org;
  62.         int row_max, col_max;
  63.         int row, col;
  64.         int first_row, first_col;
  65.         int last_row, last_col;
  66.         int first_pos, last_pos;
  67.         int char_pos;           /* current char position */
  68.         char *buff;             /* current buffer */
  69.         int no_change;
  70.         int buff_len;            /* total buffer lenght */
  71.         int attrib;              /* atrribute */
  72.         int scroll_fl;          /* scroll flag */
  73.         int box_flag;            /* box flag */
  74.         struct win_struct *next;
  75. } Window;
  76.  
  77. Window *stdscr, *firstw = 0;
  78. Window *curr_wind;
  79.  
  80. typedef struct Inkey_type {
  81.         int flen;       /* field lenght */
  82.         char *recipient;        /*the receiving the chars */
  83.         int displ_flag;         /* display flag */
  84.         int ret_val;
  85.         int char_flag;          /* to be upper or lower case  or numeric */
  86.         Window *win;
  87. } Inkey_type;
  88.  
  89.  
  90.  
  91. struct formatted {
  92.    int frow,fcol;
  93.    int flen;
  94.    int nature;                  /* alpha, ucase,numeric,flotting */
  95.    int decimal;                 /* number of decimal point */
  96.  };
  97.  
  98. double atof();
  99.  
  100.  
  101.  
  102. double getdouble();
  103. long getlong();
  104. typedef long val_t, uval_t;
  105. char *convert(), *uconvert();
  106.  
  107. static char *buff;
  108.  
  109. static double round[] = {
  110.         0.5e+0,
  111.         0.5e-1,
  112.         0.5e-2,
  113.         0.5e-3,
  114.         0.5e-4,
  115.         0.5e-5,
  116.         0.5e-6,
  117.         0.5e-7,
  118.         0.5e-8,
  119.         0.5e-9,
  120.         0.5e-10,
  121.         0.5e-11,
  122.         0.5e-12,
  123.         0.5e-13,
  124.         0.5e-14,
  125.         0.5e-15,
  126.         0.5e-16,
  127. };
  128.  
  129.  
  130. last_update(win)
  131. Window *win;
  132. {  int i, j;
  133.    if (win->first_pos == -1 || win->char_pos < win->first_pos) {
  134.        win->first_row = win->row;
  135.        win->first_col = win->col;
  136.        win->first_pos = (win->row * win->col_max + win-> col) * 2;
  137.    }
  138.    if (win->last_pos == -1 || win->last_pos < win->char_pos) {
  139.        win->last_row = win->row;
  140.        win->last_col = win->col;
  141.        win->last_pos = (win->row * win->col_max + win->col) * 2;
  142.    }
  143.    win->no_change = false;
  144. }
  145.  
  146.  
  147.  
  148. Window *  newwin(org_row, org_col, nrow, ncol)
  149. int org_row, org_col, ncol, nrow;
  150. { Window *wd;
  151.   char *pt, *pt1;
  152.   int i, j;
  153.   if (org_row < 0 || org_row > 24 || org_col < 0 || org_col > 80 ) return (0);
  154.   if (nrow < 0 || nrow + org_row > 24 || ncol < 0 || ncol + org_col > 80)
  155.        return(0);
  156.   if (!(wd = (Window *) malloc(sizeof(Window)))) return(0);
  157.   wd->buff_len = nrow * ncol * 2;
  158.   if (!(wd->buff = malloc(wd->buff_len))) {
  159.     free((char *) wd);
  160.     return(0);                  /* no more free space */
  161.   }
  162.   wd->row_max = nrow;
  163.   wd->col_max = ncol;
  164.   wd->row_org = org_row;
  165.   wd->col_org = org_col;
  166.   wd->attrib = NORMAL;          /* normal */
  167.   wd->char_pos = 0;
  168.   wd->first_pos = wd->last_pos = wd->first_row = wd->last_row =  -1;
  169.   wd->no_change = true;
  170.   wd->next = firstw;
  171.   wd->scroll_fl = false;
  172.   firstw = wd;
  173.   wd->first_pos = wd->last_pos = wd->first_col = wd->last_col = -1;
  174.   wd->first_pos = wd->last_pos = -1;
  175.   wclear(wd);
  176.   wd->char_pos = 0; wd->row = wd->col = 0;
  177.   wd->first_pos = wd->last_pos = wd->first_row = wd->last_row = -1;
  178.   wd->no_change = true;
  179.   wd->box_flag = false;
  180.   return(wd);
  181. }
  182.  
  183.  
  184.  
  185. waddch(win, mchar)
  186. Window *win;
  187. int mchar;              /* add char to window */
  188. { int i;
  189.   if (!good_window(win))return;
  190.   win->buff[win->char_pos +1] = win->attrib;       /* store attribut */
  191.   win->buff[win->char_pos] = mchar;
  192.   last_update(win);                             /* update last char pos */
  193. }
  194.  
  195.  
  196. waddstr(win, str)
  197. Window *win;
  198. char *str;
  199. {
  200.   add_string(win, str, 1);      /* add string with current attribute */
  201. }
  202.  
  203.  
  204.  
  205. wclear(win)             /* clear window */
  206. Window *win;
  207. {
  208.   if (! good_window(win)) return;
  209.   clr_buff(win->buff, win->buff_len, ' ', NORMAL);
  210.   wmove(win, win->row_max -1, win->col_max -1);
  211.   last_update(win);
  212.   wmove(win, 0, 0);
  213.   last_update(win);
  214. }
  215.  
  216.  
  217. wclrtobot(win)          /* clear to end of frame in window */
  218. Window *win;
  219. { int  i, j;
  220.   if (! good_window(win)) return;
  221.   last_update(win);
  222.   i = win->buff_len - win->char_pos;
  223.   clr_buff((win->buff) + win->char_pos, i, ' ', NORMAL);
  224.   i = win->row;
  225.   j = win->col;
  226.   wmove(win, win->row_max -1, win->col_max -1 );
  227.   last_update(win);
  228.   wmove(win, i, j);
  229. }
  230.  
  231.  
  232. wclrtoeol(win)          /* clear to end of line on window */
  233. Window *win;
  234. { int i,j;
  235.   if (!good_window(win)) return;
  236.   last_update(win);
  237.   i = (win->col_max - win->col) * 2;
  238.   clr_buff((win->buff) + win->char_pos, i, ' ', NORMAL);
  239.   i = win->col;
  240.   wmove(win, win->row, win->col_max -1);
  241.   last_update(win);
  242.   wmove(win, win->row, i);
  243.  
  244. }
  245.  
  246.  
  247. wdelch(win)             /* delete char from window */
  248. Window *win;
  249. { int i, j;
  250.   char *pt, *pt1;
  251.   if (!(good_window(win))) return;
  252.   last_update(win);
  253.   i = (win->col_max - win->col -1) *2;
  254.   pt = win->buff + win->char_pos;
  255.   for (pt1 = pt +2 ; i > 0; *pt ++ = *pt1 ++, i--);
  256.   *pt ++ = ' '; /* blank end of line */
  257.   *pt = win->attrib;
  258.   i = win->col;
  259.   wmove(win, win->row, win->col_max -1);
  260.   last_update(win);
  261.   wmove(win, win->row, i);
  262. }
  263.  
  264.  
  265.  
  266. wdeleteln(win)          /* delete one line from the window */
  267. Window *win;
  268. { int i, j;
  269.   char *pt, *pt1;
  270.   if (! good_window(win)) return;
  271.   i = (win->row_max - win->row - 1) * win->col_max * 2; /* # oc cols */
  272.   pt = win->buff + win->row * win->col_max * 2;
  273.   if (i ) {
  274.     pt1 = pt + win->col_max * 2;  /* we are going to move things backward */
  275.     for (; i > 0; *pt ++ = *pt1 ++, i--);
  276.   }
  277.   i = win->row;
  278.   clr_buff(pt, win->col_max * 2, ' ', win->attrib);  /* clear last line */
  279.   wmove(win, win->row_max -1, win->col_max -1);
  280.   last_update(win);
  281.   wmove(win, i, 0);
  282.   last_update(win);
  283. }
  284.  
  285.  
  286. wexptab(win)            /*expand tab in the window */
  287. Window *win;
  288. {  int i;
  289.    if (! good_window(win)) return;
  290.    i = (win->col - win->col % 8) + 8;
  291.    if (i >= win->col_max) i = win->col_max - 1;
  292.    wmove(win, win->row, i);
  293. }
  294.  
  295.  
  296. winch(win)                 /* get one char from screen */
  297. Window *win;
  298. { char *pt;
  299.   unsigned int i, j;
  300.   if (! good_window(win)) return;
  301.   pt = win->buff + win->char_pos;
  302.   i = *pt  + *(pt +1) * 256;       /* pack char and attribute */
  303.   return(i);
  304. }
  305.  
  306.  
  307.  
  308. winsch(win, ch)      /* insert a char */
  309. Window *win;
  310. int ch;
  311. { int i, j;
  312.   char *pt, *pt1;
  313.   if (! good_window(win)) return;
  314.   last_update(win);
  315.   i = (win->row +1) * win->col_max * 2 - 3;
  316.   pt1 = win->buff + i;   /* end of buffer - 1 char */
  317.   pt = pt1 +2;          /* end of buffer */
  318.   i = (win->col_max - win->col -1) * 2;
  319.   for (; i > 0; *pt -- = *pt1 --, i--); /* move backward */
  320.   *pt -- = win->attrib;    /* attribute   */
  321.   *pt  = ch ;                   /* insert ch */
  322.   i = win->col;
  323.   wmove(win, win->row, win->col_max -1);
  324.   last_update(win);
  325.   wmove(win, win->row, i);
  326. }
  327.  
  328.  
  329. winsertln(win)          /* insert a line  in window */
  330. Window *win;
  331. { int i, j;
  332.   char *pt, *pt1;
  333.   if (! good_window(win)) return;
  334.   wmove(win, win->row, 0);
  335.   last_update(win);
  336.   pt1 = win->buff + win->buff_len -1;   /* end of buffer */
  337.   pt  = pt1 - win->col_max * 2;             /* source to move */
  338.   i = (win->row_max - win->row -1) * win->col_max *2; /* # of elems */
  339.   for (; i > 0; i--, *pt1 -- = *pt --);  /* move now */
  340.   wclrtoeol(win);
  341.   j = win->row;
  342.   wmove(win, win->row_max -1, win->col_max -1);
  343.   last_update(win);
  344.   wmove(win, j, 0);
  345. }
  346.  
  347.  
  348.  
  349. wmove(win, row, col)
  350. int row, col;
  351. Window *win;
  352. {
  353.   if (!good_window(win)) return;
  354.   win->row = row % win->row_max;
  355.   win->col = col % win->col_max;
  356.   win->char_pos = (win->row * win->col_max + win->col) * 2;
  357. }
  358.  
  359.  
  360. woverch(win, mchar)
  361. Window *win;
  362. int mchar;
  363. { if (! good_window(win)) return;
  364.   win->buff[win->char_pos] = mchar;
  365.   last_update(win);
  366. }
  367.  
  368.  
  369. woverstr(win, s)        /* overlay string over some thing */
  370. Window *win;
  371. char *s;
  372. {       /* add sgtring without changing the attribute */
  373.    add_string(win, s, 0);
  374. }
  375.  
  376.  
  377.  
  378. wprintf(fmt, args)
  379. char *fmt;
  380. unsigned args;
  381. {  char s[200];
  382.    buff = s;
  383.    format(mcv, fmt, &args);
  384.    *buff = 0;
  385.    addstr(s);
  386. }
  387.  
  388.  
  389. wprintfw(win, fmt, args)
  390. Window  * win;
  391. char *fmt;
  392. unsigned args;
  393. { char s[200];
  394.   buff = s;
  395.   format(mcv, fmt,&args);
  396.   *buff = 0;
  397.   waddstr(win, s);
  398. }
  399.  
  400.  
  401.  
  402. mcv(c)
  403. { return(*buff ++ = c & 0xff); }
  404.  
  405.  
  406.  
  407. wrefresh(win)           /* refresh window */
  408. Window *win;
  409. {  int colx, rowx, row, col, i, j, n, m;
  410.    char *pt;
  411.    if (! good_window(win)) return;
  412.    if (win->no_change || win->first_pos == -1 || win->last_pos == -1) {
  413.         locate(win->row + win->row_org, win->col + win->col_org);
  414.         return;
  415.    }
  416.    m = win->col_max * 2;
  417.    rowx = win->first_row + win->row_org;
  418.    pt = win->first_pos + win->buff;
  419.    col = win->first_col;
  420.    i = win->last_pos - win->first_pos + 2;   /* total number of char to send */
  421.    for (row = win->first_row; i > 0 && row <= win->last_row; rowx ++, row ++) {
  422.      colx = win->col_org + col;
  423.      j = (win->col_max - col) * 2;   /* compute number of chars to send */
  424.      n = (j < i) ? j : i;
  425.      loc_update(rowx, colx, pt, n/2);
  426.      pt += n ;
  427.      i -= n ;
  428.      col = 0;
  429.    }
  430.    locate(win->row + win->row_org, col + win->col + win->col_org);
  431.    set_nochange(win);
  432.  }
  433.  
  434.  
  435.  
  436.  
  437. wscroll(win)            /* scroll up */
  438. Window *win;
  439. {  int i, j;
  440.    char *pt, *pt1;
  441.   if (! good_window(win)) return;
  442.   u_scroll(win->row_org, win->col_org, win->row_org + win->row_max - 1,
  443.                          win->col_org + win->col_max - 1);
  444.   memcpy(win->buff, win->buff + (i = win->col_max *2),
  445.                    (j = (win->row_max -1) * win->col_max * 2));
  446.   clr_buff(win->buff + j, i, ' ', NORMAL);
  447.   pt = win->buff;               /* transfer window to screen pad */
  448.   pt1 = scr_buff+(win->row_org * 80 + win->col_org)*2; /* offset into buffer */
  449.   j = win->col_max * 2;
  450.   for (i = 0 ; i < win->row_max; i++) {
  451.     memcpy(pt1, pt, j);                 /* move one row of infow */
  452.     pt1 += 80 * 2;              /* next row on the screen */
  453.     pt += j;
  454.   }
  455.   set_nochange(win);
  456. }
  457.  
  458.  
  459. wstandend(win)          /* hilit end */
  460. Window *win;
  461. {
  462.    if (! good_window(win)) return;
  463.    win->attrib &= ~HILIT_ON;   /* hilit off manifest constant */
  464. }
  465.  
  466.  
  467. wstandout(win)
  468. Window *win;
  469. {
  470.   if (! good_window(win)) return;
  471.   win->attrib |= HILIT_ON;
  472. }
  473.  
  474.  
  475.  
  476. wsetattrib(win, atrb)           /* set window attribute */
  477. Window *win;
  478. int atrb;
  479. { int i;
  480.   if ( ! good_window(win)) return;
  481.   win->attrib  = atrb;
  482. }
  483.  
  484.  
  485. wusetattrib(win, atrb)          /* unset attribute */
  486. Window *win;
  487. int atrb;
  488. {
  489.    if (! good_window(win)) return;
  490.    win->attrib  = NORMAL;
  491. }
  492.  
  493.  
  494.  
  495. scrollok(win, ok)                /* scroll ok */
  496. Window *win;
  497. int ok;
  498. {
  499.   if (! good_window(win)) return;
  500.   win->scroll_fl = ok;
  501. }
  502.  
  503.  
  504.  
  505. box(win)
  506. Window *win;
  507. {  int i, j, row, col;
  508.    char s[3];
  509.    if (! good_window(win)) return(BAD);
  510.    row = win->row_org - 1;
  511.    col = win->col_org -1 ;
  512.    s[1] = NORMAL;
  513.    if (win->row_org == 0 || win->col_org == 0 || win->row_max == NROWS
  514.                          || win->col_max == NCOLS) return;
  515.    col = win->col_org - 1;
  516.    row = win->row_org -1;
  517.    for (i = 0; i <= win->row_max +1; i++, row ++) {
  518.      if (i == 0 ) {
  519.        s[0] = 201;            /* left corner */
  520.        box_char(row, col, s);
  521.        s[0] = 187;                     /* right corner */
  522.        box_char(row, win->col_org + win->col_max, s);
  523.      }
  524.      if (i == win->row_max +1 || i == 0 ) {
  525.        s[0] = 205;
  526.        for (j = 1; j <  win->col_max +1; j++)
  527.               box_char(row, j + col, s);
  528.      }
  529.      if (i == win->row_max+1) {
  530.        s[0] = 200;              /* leeft down corner */
  531.        box_char(row, col, s);
  532.        s[0] = 188;              /* right down corner */
  533.        box_char(row, col + win->col_max + 1, s);
  534.      }
  535.      if ( i && i != win->row_max +1) {
  536.        s[0] = 186;
  537.        box_char(row, col, s);
  538.        box_char(row, col+ win->col_max+1, s);
  539.      }
  540.    }
  541.   win->box_flag = true;
  542. }
  543.  
  544.  
  545. box_char(row, col,s )
  546. int row, col;
  547. char *s;
  548. { char *p;
  549.   p = scr_buff + (row * NCOLS + col) * 2;
  550.   *p ++ = *s;
  551.   *p = s[1];
  552.   write_attrib(row, col, s);
  553. }
  554.  
  555.  
  556.  
  557. delwin(win)             /* get rid of a wondow */
  558. Window *win;
  559. { Window *wd, *wd1;
  560.   int done;
  561.   if (! good_window(win)) return(BAD);
  562.    if (win->box_flag) erase_box(win);
  563.    wclear(win);
  564.    wrefresh(win);
  565.    free(win->buff);
  566.    for (wd = wd1 = firstw, done = false; ! done; ) {
  567.      if (wd == win) done = true;
  568.      else {
  569.        wd1 = wd;
  570.        wd = wd->next;
  571.      }
  572.    }
  573.    wd1->next = wd->next;
  574.    if (wd == firstw) firstw = wd->next;
  575.    free((char *) win);
  576.    return(GOOD);
  577.  }
  578.  
  579.  
  580.  
  581. erase_box(win)
  582. Window *win;
  583. {  int i, j, row, col;
  584.    char s[3];
  585.    if (! good_window(win)) return(BAD);
  586.    row = win->row_org - 1;
  587.    col = win->col_org -1 ;
  588.    s[1] = NORMAL;
  589.    s[0] = ' ';
  590.    if (win->row_org == 0 || win->col_org == 0 || win->row_max == NROWS
  591.                          || win->col_max == NCOLS) return;
  592.    col = win->col_org - 1;
  593.    row = win->row_org -1;
  594.    for (i = 0; i <= win->row_max +1; i++, row ++) {
  595.      if (i == 0 ) {
  596.        box_char(row, col, s);
  597.        box_char(row, win->col_org + win->col_max, s);
  598.      }
  599.      if (i == win->row_max +1 || i == 0 ) {
  600.        for (j = 1; j <  win->col_max +1; j++)
  601.               box_char(row, j + col, s);
  602.      }
  603.      if (i == win->row_max+1) {
  604.                                 /* leeft down corner */
  605.        box_char(row, col, s);
  606.                                 /* right down corner */
  607.        box_char(row, col + win->col_max + 1, s);
  608.      }
  609.      if ( i && i != win->row_max +1) {
  610.        box_char(row, col, s);
  611.        box_char(row, col+ win->col_max+1, s);
  612.      }
  613.    }
  614. }
  615.  
  616.  
  617. touch(win)
  618. Window *win;
  619. { int row, col, rowx, colx;
  620.   if (! good_window(win)) return;
  621.   win->first_row = win->first_col = win->first_pos = 0;
  622.   win->last_row = win->row_max - 1;
  623.   win->last_col = win->col_max - 1;
  624.   win->last_pos = win->row_max * 2 * win->col_max;
  625.   win->no_change = false;
  626.   wrefresh(win);
  627.   if (win->box_flag) box(win);
  628. }
  629.  
  630.  
  631. add_string(win, str, attrib_flag)
  632. Window *win;
  633. char *str;
  634. int attrib_flag;
  635. { int i, j;
  636.   char *pt;
  637.   if (! good_window(win)) return;
  638.   pt = win->buff + win->char_pos;
  639.   last_update(win);
  640.   for ( i = win->col; *str && i < win->col_max; i ++, str ++) {
  641.     *pt ++ = *str;
  642.     if (attrib_flag) *pt ++ = win->attrib;
  643.     else pt ++;                 /* add string conserving the attribute*/
  644.     win->char_pos += 2;
  645.   }
  646.   j = win->col;
  647.   if (i >= win->col_max) i = win->col_max -1 ;
  648.   wmove(win, win->row, i);
  649.   last_update(win);
  650.   wmove(win, win->row, j);      /* restore last cursor position */
  651.  }
  652.  
  653.  
  654. clr_buff(s, len, c, attrib)
  655. int len, attrib;
  656. char *s, c;
  657. {  int i, j;
  658.    for (i = 0; i < len; i += 2) {
  659.       *s ++ = c;
  660.       *s ++ = attrib;
  661.    }
  662.  }
  663.  
  664.  
  665. good_window(win)
  666. Window *win;
  667. { int found;
  668.   Window *fw;
  669.   for (found = false, fw = firstw; !found && fw; fw = fw->next) {
  670.     if (win == fw) {
  671.        found = true;
  672.        break;
  673.     }
  674.   }
  675.   return(found);
  676. }
  677.  
  678.  
  679.  
  680. loc_update(row, col, pt, len)  /* update the location on the screen */
  681. int row, col, len;
  682. char *pt;
  683. { int i, j;
  684.   char *pt1;
  685.   struct SREGS sregs;
  686.   i = (row * 80 + col) * 2;
  687.   pt1 = scr_buff + i;
  688.   if (retrace) {
  689.     for (i = 0; i < len ; i++, col ++) {
  690.       if (*pt != *pt1 || *(pt+1) != *(pt1 + 1)) {
  691.         write_attrib(row, col, pt);
  692.         *pt1 ++ = *pt ++;     /* uptdate these locations */
  693.         *pt1 ++ = *pt ++;
  694.       }
  695.       else {
  696.         pt += 2;
  697.         pt1 += 2;
  698.       }
  699.     }
  700.   }
  701.   else {   /* move directly to screen if in an ibm */
  702.     movedata(FP_SEG(pt), FP_OFF(pt), 0xb000, i, len * 2);
  703.     memcpy(pt1, pt, len * 2);   /* update memory too */
  704.   }
  705. }
  706.  
  707.  
  708. noraw()           /* raw mode set */
  709. {  union REGS inreg, outreg;
  710.    inreg.x.bx = 1;                      /* i/o control read request */
  711.    inreg.x.ax = 0x4400;
  712.    int86(0x21, &inreg, &outreg);        /* i/o control read */
  713.    inreg = outreg;
  714.    inreg.h.dh = 0;
  715.    inreg.h.dl &= ~ 0x20;          /* set raw bit */
  716.    inreg.x.bx = 1;              /* i/o control write request */
  717.    inreg.x.ax = 0x4401;
  718.    int86(0x21, &inreg, &outreg);
  719. }
  720.  
  721. raw()           /* raw mode set */
  722. {  union REGS inreg, outreg;
  723.    inreg.x.bx = 1;                      /* i/o control read request */
  724.    inreg.x.ax = 0x4400;
  725.    int86(0x21, &inreg, &outreg);        /* i/o control read */
  726.    inreg = outreg;
  727.    inreg.h.dh = 0;
  728.    inreg.h.dl |= 0x20;          /* set raw bit */
  729.    inreg.x.bx = 1;              /* i/o control write request */
  730.    inreg.x.ax = 0x4401;
  731.    int86(0x21, &inreg, &outreg);
  732. }
  733.  
  734.  
  735.  
  736. set_nochange(win)
  737. Window *win;
  738. {  win->no_change = true;
  739.    win->first_row = win->last_row = win->first_col = win->last_col = -1;
  740.    win->first_pos = win->last_pos = -1;
  741.  }
  742.  
  743.  
  744. u_scroll(y0, x0, y3, x3)        /* scroll up */
  745. int y0, x0, y3, x3;
  746. {
  747.   do_scroll(y0, x0, y3, x3, 6);
  748. }
  749.  
  750. d_scroll(y0, x0, y3, x3)        /* down scroll */
  751. int y0, x0, y3, x3;
  752. {
  753.   do_scroll(y0, x0, y3, x3, 7);
  754. }
  755.  
  756.  
  757. do_scroll(row0, col0, row3, col3, call_type)      /* scroll up */
  758. int row0, col0, col3, row3, call_type;
  759. { union REGS inreg, outreg;
  760.   inreg.h.ch = row0;      /* set x0, y0 */
  761.   inreg.h.cl = col0;
  762.   inreg.h.dh = row3;
  763.   inreg.h.dl = col3;
  764.   inreg.h.bh = NORMAL;
  765.   inreg.h.al = 1;
  766.   inreg.h.ah = call_type;       /* service code */
  767.   int86(rom_call, &inreg, &outreg);
  768. }
  769.  
  770. cursorsize(begl, endl)
  771. int begl,endl;
  772. {  union REGS inreg, outreg;
  773.    inreg.h.ah = 1;              /* set cursor position */
  774.    inreg.h.cl = endl;
  775.    inreg.h.ch = begl;
  776.    int86(rom_call, &inreg, &outreg);
  777. }
  778.  
  779.  
  780. /*** end of active routines */
  781.  
  782.  
  783. /* ##a */
  784.  
  785.  
  786. alinkey(nrow, ncol, message, len, s)
  787. int nrow, ncol, len;
  788. char *s, *message;
  789. {  int i, j;
  790.    char_clear(s, len, ' ');
  791.    return(get_inkstring(stdscr, nrow, ncol, message, len, s));
  792. }
  793.  
  794.  
  795. /* ##b */
  796.  
  797. bell()
  798. { putchar(7); }
  799.  
  800. /* ##c */
  801.  
  802.  
  803.  
  804. static char_clear(s, len, c)
  805. register char *s, c;
  806. register int len;
  807. {
  808.    for (; len > 0 ; *s ++ = c, len--);
  809.    *s = 0;
  810. }
  811.  
  812.  
  813. cls()           /* clear screen */
  814. { union REGS inreg, outreg;
  815.   inreg.x.ax = 0x7;     /* set mode and clear screen */
  816.   int86(rom_call, &inreg, &outreg);
  817.   if (scr_buff != 0) clr_buff(scr_buff, 80 * 24 * 2, ' ', NORMAL);
  818. }
  819.  
  820. cls_eol(row, col)
  821. int row, col;
  822. { int i, j;
  823.   union REGS inreg, outreg;
  824.   locate(row, col);
  825.   if (! (inreg.x.cx = 80 - col)) return;
  826.   inreg.x.bx = 0x7;     /* normal mode*/
  827.   inreg.h.ah = 9;       /* service call */
  828.   inreg.h.al = 32;      /* char to used */
  829.   int86(rom_call, &inreg, &outreg);
  830. }
  831.  
  832.  
  833.  
  834. cls_eof(row, col)        /* clear to end of screen */
  835. int row, col;
  836. { int i, j;
  837.   union REGS inreg, outreg;
  838.   locate(row, col);
  839.   inreg.x.cx = (24 - row) * 80 - col;
  840.   inreg.x.bx  = 0x7;    /* attributes */
  841.   inreg.h.al = 32;
  842.   inreg.h.ah = 9;       /* service call */
  843.   int86(rom_call, &inreg, &outreg);
  844. }
  845.  
  846.  
  847. concate(s, s1, s2)
  848. char *s, *s1, *s2;
  849. { strcpy(s, s1);
  850.   strcat(s, s2);
  851. }
  852.  
  853.  
  854.  
  855. /* ##d   */
  856.  
  857. doinput(curr_wind, finput, recip, ret_val)
  858. Window *curr_wind;
  859. int *ret_val;
  860. char *recip;
  861. struct formatted *finput;
  862. {  char s[300], s1[300];
  863.    int i, j;
  864.    Window win;
  865.    Inkey_type ink;
  866.    double temp;
  867.    if (finput->nature == numeric || finput->nature == floatting) {
  868.       trim(s, recip);                   /* left justify numeric */
  869.       lset(recip, s);                   /* do it now */
  870.       ink.char_flag = (finput->decimal) ? numeric : floatting;
  871.    }
  872.    else ink.char_flag = finput->nature;
  873.    ink.flen = finput->flen;
  874.    ink.ret_val = *ret_val;
  875.    win.next = firstw;
  876.    firstw = &win;                /* add tenmporary to list */
  877.    set_winkey(curr_wind, &win, finput->frow, finput->fcol, finput->flen);
  878.    ink.win = &win;
  879.    ink.displ_flag = true;
  880.    ink.recipient = recip;
  881.    wmove(curr_wind, finput->frow, finput->fcol);
  882.    win.attrib = ret_attrib(curr_wind);  /* get attribute at location */
  883.    zaskey(&ink);
  884.    if (finput->nature == numeric || finput->nature == floatting) {
  885.      temp = atof(recip);
  886.      if (finput->decimal == 0) {
  887.         sprintf(s1, "%%%dd", finput->flen);
  888.         sprintf(s, s1, (int) temp);
  889.         rset(recip, s);
  890.      }
  891.      else {
  892.        sprintf(s1, "%%%d.%df", finput->flen, finput->decimal);
  893.        sprintf(s, s1, temp);
  894.        rset(recip, s);
  895.     }
  896.     wmove(&win, 0, 0);
  897.     woverstr(&win, recip);
  898.     wrefresh(&win);
  899.   }
  900.   *ret_val = ink.ret_val;
  901.   firstw = win.next;
  902. }
  903.  
  904.  
  905. /* ##e */
  906.  
  907.  
  908. error_message(message)
  909. char *message;
  910. { bell();
  911.   cls_eol(24, 0);
  912.   cprintf("%s", message);
  913.   kcget();
  914.   cls_eol(24, 0);
  915. }
  916.  
  917.  
  918. /* ##f */
  919.  
  920. fill_char(s, len, ch)
  921. char *s, ch;
  922. int len;
  923. { int i;
  924.   for (i = 0; i ++ < len; *s ++ = ch);
  925.   *s = 0;
  926. }
  927.  
  928.  
  929. filter(mchar)
  930. int mchar;
  931. {  int i, j, cmc;
  932.    if ((cmc = mchar) >= 32 && mchar <= 127) return(mchar);
  933.    if (!cmc) {
  934.      cmc = single_char();
  935.      j = 2;
  936.    }
  937.    else j = 1;
  938.    for (i= 0; i < nkey; ) {
  939.      if (key_code[i][j] == cmc) {
  940.        if (j == 4) return(key_code[i][0]);
  941.        if ( !key_code[i][j+1]) return(key_code[i][0]);
  942.        j ++; cmc = single_char();
  943.      }
  944.      else i++;
  945.    }
  946.    return(mchar);
  947.  }
  948.  
  949.  
  950.  
  951. /* ##g */
  952.  
  953. get_inkstring(inwind, nrow, ncol, message, len, s)
  954. Window *inwind;
  955. int nrow, ncol, len;
  956. char *message, *s;
  957. { int i, j;
  958.    Window win;
  959.    Inkey_type ink;
  960.    ink.char_flag = ucase;
  961.    ink.ret_val = 0;
  962.    wmove(inwind, nrow, ncol);
  963.    wstandout(inwind);
  964.    waddstr(inwind, message);
  965.    wstandend(inwind);
  966.    wrefresh(inwind);
  967.    win.next = firstw;
  968.    firstw = &win;                /* add tenmporary to list */
  969.    set_winkey(inwind, &win, nrow, ncol + strlen(message)+1, len);
  970.    ink.displ_flag = true;
  971.    ink.recipient = s;
  972.    ink.win = &win;
  973.    win.attrib = UNDERLINE;
  974.    wmove(&win, 0, 0);
  975.    waddstr(&win, s);
  976.    zaskey(&ink);
  977.    firstw = win.next;    /* restore firstw */
  978.    return(ink.ret_val);
  979. }
  980.  
  981.  
  982. /* ##i  */
  983.  
  984. inkey(finput, recip, ret_val)
  985. int *ret_val;
  986. char *recip;
  987. struct formatted *finput;
  988. {
  989.   doinput(curr_wind, finput, recip, ret_val);
  990. }
  991.  
  992.  
  993.  
  994.  
  995. initscr()
  996. {
  997.    if (! (stdscr = newwin(0, 0, 24, 80))) exit();
  998.    cls();
  999.    if ( !(scr_buff = malloc(80 *24 * 2))) {
  1000.       fprintf(stderr, "Out of memory\n");
  1001.       exit();
  1002.    }
  1003.    memcpy(scr_buff, stdscr->buff, 80*24*2);
  1004.    curr_wind = stdscr;          /* set current window to stdscr */
  1005.    /* touch(stdscr); */
  1006. }
  1007.  
  1008.  
  1009. instring(s, s1)
  1010. register char *s1, *s;
  1011. { register char *p;
  1012.   register i, j;
  1013.   for (i = strlen(s), j = strlen(s1), p = s; i >= j; p++, i--) {
  1014.     if (!strncmp(p, s1, j)) return((int) (p -s));
  1015.   }
  1016.   return(-1);
  1017. }
  1018.  
  1019. /* ##k */
  1020.  
  1021. kcget()
  1022. {
  1023.    return(filter(single_char() & 0xff));
  1024. }
  1025.  
  1026.  
  1027.  
  1028. kcinit()        /* init the keyboard filter */
  1029. { FILE *fd, *fopen();
  1030.   char line[90], s[50], *getenv();
  1031.   int n, i;
  1032.   concate(s, "/terminal/", getenv("KEYB"));
  1033.   if (!(fd = fopen(s, "r"))) {
  1034.      fprintf(stderr, "Cannot open the keyboad configuration file %s\n", s);
  1035.      exit();
  1036.   }
  1037.   n = fileno(fd);
  1038.   setmode(n, O_TEXT);           /* make sure we are in text mode */
  1039.   for ( nkey = 0; fgets(line, 80, fd); nkey ++) {
  1040.     sscanf(line, "%d %d %d %d %d", &key_code[nkey][0], &key_code[nkey][1],
  1041.               &key_code[nkey][2], &key_code[nkey][3], &key_code[nkey][4]);
  1042.   }
  1043.   fclose(fd);
  1044.   retrace = atoi(getenv("RETRACE"));
  1045.   open_printer();
  1046.   line_size = 80;
  1047.   user_page = 20;
  1048.   page_size = 24;
  1049. }
  1050.  
  1051.  
  1052. key_punched()
  1053. {  union REGS inreg, outreg;
  1054.    inreg.h.ah = 0x0b;
  1055.    intdos(&inreg, &outreg);
  1056.    return(outreg.h.al);
  1057. }
  1058.  
  1059.  
  1060. /* ##l  */
  1061.  
  1062. left_trim(s, s1)                /* trim leading blanks */
  1063. register char *s1, *s;
  1064. { int i, j;
  1065.   for (; *s1 && *s1 == ' '; s1 ++);  /* found first non blk */
  1066.   strcpy(s, s1);                      /* copy remainder to s */
  1067. }
  1068.  
  1069.  
  1070. locate(row, col)
  1071. int row, col;
  1072. {  union REGS inreg, outreg;
  1073.    inreg.h.bh = 0;        /* page number */
  1074.    inreg.h.dh = row;
  1075.    inreg.h.dl = col;
  1076.    inreg.h.ah = 2;        /* service number */
  1077.    int86(rom_call, &inreg, &outreg);
  1078. }
  1079.  
  1080.  
  1081. lset(s, s1)
  1082. char *s1, *s;
  1083. {  fill_char(s, strlen(s), ' ');
  1084.    left_trim(s1, s1);
  1085.    for (; *s && *s1; *s ++ = *s1 ++);
  1086. }
  1087.  
  1088.  
  1089. /* ##n  */
  1090.  
  1091. ninkey(nrow, ncol, message, len)
  1092. int nrow, ncol, len;
  1093. char *message;
  1094. {  Inkey_type ink;
  1095.    char s[200];
  1096.    Window win, *inwind;
  1097.    int i;
  1098.    inwind = stdscr;
  1099.    ink.displ_flag = false;
  1100.    ink.ret_val = 0;
  1101.    ink.char_flag = numeric;
  1102.    ink.recipient = s;
  1103.    char_clear(s, len, ' ');
  1104.    wstandout(inwind);
  1105.    wmove(inwind, nrow, ncol);
  1106.    waddstr(inwind, message);
  1107.    wstandend(inwind);
  1108.    wrefresh(inwind);
  1109.    win.next = firstw;
  1110.    firstw = &win;
  1111.    set_winkey(inwind, &win, nrow, ncol + strlen(message) +1, len);
  1112.    ink.win = &win;
  1113.    win.attrib = UNDERLINE;
  1114.    zaskey(&ink);
  1115.    firstw = win.next;          /* reset firsw to its previous value */
  1116.    return(atoi(s));
  1117. }
  1118.  
  1119. /* ##o */
  1120.  
  1121.  
  1122.  
  1123. one_char()              /* get achar from key */
  1124. {
  1125.   return(kcget());
  1126. }
  1127.  
  1128.  
  1129. open_printer()
  1130. {  printer = fileno(stdprn);
  1131.    setmode(printer, O_BINARY);
  1132. }
  1133.  
  1134. /* ##p */
  1135.  
  1136. print_at(row, col, s)
  1137. int row, col;
  1138. char *s;
  1139. {  if (row < 24) {
  1140.      mvprint(row, col, s);
  1141.    }
  1142.    else {
  1143.      locate(row, col);
  1144.      cprintf("%s", s);
  1145.    }
  1146. }
  1147.  
  1148.  
  1149. /* ##r  */
  1150.  
  1151. ret_attrib(win)
  1152. Window *win;
  1153. {  return(win->buff[win->char_pos+1]);
  1154. }
  1155.  
  1156.  
  1157. right_trim(s, s1)
  1158. char *s;
  1159. register char *s1;
  1160. { register int i, j;
  1161.   i = strlen(s1) - 1;
  1162.   for (; i >= 0 && s1[i] == ' '; i--);
  1163.   if (i < 0) *s = 0;
  1164.   else {
  1165.     s1[i+1] = 0;
  1166.     strcpy(s, s1);
  1167.   }
  1168. }
  1169.  
  1170.  
  1171. rset(s, s1)
  1172. char *s, *s1;
  1173. { int i, j;
  1174.   trim(s1, s1);
  1175.   fill_char(s, (i = strlen(s)), ' ');
  1176.   j = strlen(s1) - 1;
  1177.   for ( i--; i >= 0 && j >= 0; s[i --] = s1[j--]);
  1178. }
  1179.  
  1180.  
  1181. /* ##s  */
  1182.  
  1183.  
  1184. set_winkey(inwind, win, nrow, ncol, len)
  1185. Window *inwind, *win;
  1186. int nrow, ncol, len;
  1187. {  int i;
  1188.    win->row_org = inwind->row_org + nrow;
  1189.    win->col_org = inwind->col_org + ncol;
  1190.    win->col_max = len;
  1191.    win->row_max = 1;
  1192.    i = (nrow * inwind->col_max + ncol) * 2;
  1193.    win->buff = inwind->buff + i;
  1194.    wmove(win, 0, 0);
  1195.    win->attrib = inwind->attrib;
  1196.    set_nochange(win);
  1197. }
  1198.  
  1199.  
  1200. single_char()           /* just read one single char */
  1201. {  union REGS inreg, outreg;
  1202.    inreg.h.ah = 8;              /* bdos call for input char */
  1203.    inreg.x.dx = inreg.x.cx = 0;
  1204.    intdos(&inreg, &outreg);
  1205.    return(outreg.h.al & 0xff);
  1206. }
  1207.  
  1208.  
  1209. space(s)
  1210. char *s;
  1211. { for (; *s && *s == ' '; s++);
  1212.   return ( (*s) ? false : true)  ;
  1213. }
  1214.  
  1215.  
  1216. /* ##t */
  1217.  
  1218.  
  1219. trim(s, s1)
  1220. char *s, *s1;
  1221. {  left_trim(s, s1);
  1222.    right_trim(s, s);
  1223. }
  1224.  
  1225.  
  1226. /* ##w  */
  1227.  
  1228.  
  1229. write_attrib(row, col, pt)
  1230. int row, col;
  1231. char *pt;
  1232. { union REGS inreg, outreg;
  1233.   locate(row, col);
  1234.   inreg.h.bh = 0;       /* page one */
  1235.   inreg.h.al = *pt ++ ;     /* char to write */
  1236.   inreg.h.bl = *pt;     /* atrribute */
  1237.   inreg.x.cx = 1;       /* number of chars */
  1238.   inreg.h.ah = 9;       /* rom call service number */
  1239.   int86(rom_call, &inreg, &outreg);
  1240. }
  1241.  
  1242.  
  1243. winkey(win, finput, recip, ret_val)
  1244. int *ret_val;
  1245. Window *win;
  1246. char *recip;
  1247. struct formatted *finput;
  1248. {
  1249.   doinput(win, finput, recip, ret_val);
  1250. }
  1251.  
  1252. /* ##z */
  1253.  
  1254. zaskey(ink)
  1255. Inkey_type *ink;
  1256. {  int c,  done, used, i, ins_flag, store_flag;
  1257.    char *p, *s ;
  1258.    ins_flag = false;
  1259.    wmove(ink->win, 0, 0);
  1260.    if (ink->displ_flag) woverstr(ink->win, ink->recipient);
  1261.    else {
  1262.         for (i = 0, c = ' '; i < ink->win->col_max; i++) {
  1263.                 wmove(ink->win, 0, i);
  1264.               woverch(ink->win, c);
  1265.         }
  1266.    }
  1267.    wrefresh(ink->win);
  1268.    for (used = 0, done = false; ! done; ) {
  1269.        wmove(ink->win, 0, used);
  1270.        wrefresh(ink->win);
  1271.        switch((c = kcget())) {
  1272.           case  BACKSPACE :
  1273.           case  LEFT      :   if (used > 0) used --;
  1274.                               break;
  1275.           case  RIGHT     :   if (used < ink->win->col_max - 1) used ++;
  1276.                               else if (ink->ret_val == -1) {
  1277.                                 ink->ret_val = RIGHT;
  1278.                                 done = true;
  1279.                               }
  1280.                               break;
  1281.           case  ESC       :
  1282.           case  UP        :
  1283.           case DOWN       :
  1284.           case  F10       :
  1285.           case  13        :   done = true;
  1286.                               ink->ret_val = c;
  1287.                               break;
  1288.           case  INSERT    :   ins_flag = ins_flag ? false : true;
  1289.                               break;
  1290.           case  DELETE    :   wdelch(ink->win);
  1291.                               break;
  1292.           default         :   store_flag = false;
  1293.                               c &= 0xff;
  1294.                               if (isascii(c) || c == '.') {
  1295.                                 if (ink->char_flag == numeric ||
  1296.                                          ink->char_flag == floatting) {
  1297.                                   if (c == '-' || c == '+' || isdigit(c)
  1298.                                       || c == '.'    || c == ' ') {
  1299.                                        store_flag = true;
  1300.                                   /* if (c == '.' && ink->char_flag !=floatting)
  1301.                                           store_flag = false;   */
  1302.                                   }
  1303.                                 }
  1304.                                 else {
  1305.                                    if (ink->char_flag == ucase) c = toupper(c);
  1306.                                    store_flag = true;
  1307.                                 }
  1308.                               }
  1309.                               if (store_flag) {
  1310.                                 if (ins_flag) {
  1311.                                    winsch(ink->win, c);
  1312.                                 }
  1313.                                 else woverch(ink->win, c);
  1314.                                 if (used < ink->win->col_max - 1) used ++;
  1315.                                 else if (ink->ret_val == -1) {
  1316.                                   ink->ret_val = 13;
  1317.                                   done = true;
  1318.                                 }
  1319.                               }
  1320.         }
  1321.     }
  1322.     p = ink->win->buff;
  1323.     for (s = ink->recipient, i = 0; i < ink->win->col_max; i++) {
  1324.         *s ++ = *p ++;
  1325.         *p++;           /* pass the attribute */
  1326.     }
  1327.     *s = 0;
  1328.     wrefresh(ink->win);
  1329. }
  1330.  
  1331.  
  1332. wprint_at(win, row, col, s)
  1333. Window *win;
  1334. int row, col;
  1335. char *s;
  1336. {
  1337.    wmove(win, row, col);
  1338.    waddstr(win, s);
  1339.    wrefresh(win);
  1340. }
  1341. /* ****************************  FORNAT PROGRAM */
  1342.  
  1343. format(putsub, fmt, args)
  1344. register int (*putsub)(); register char *fmt; char  *args;
  1345. {
  1346.         register int c;
  1347.         int rj, fillc, *intarg;
  1348.         int maxwidth, width;
  1349.         val_t value;
  1350.         long *longarg;
  1351.         int i, k;
  1352.         unsigned *oldarg;
  1353.         char *cp, **ap;
  1354.         char s[400];
  1355.         double dval;
  1356.  
  1357.         while ( c = *fmt++ ) {
  1358.                 if ( c == '%' ) {
  1359.                         oldarg = args;
  1360.                         s[14] = 0;
  1361.                         rj = 1;
  1362.                         fillc = ' ';
  1363.                         maxwidth = 0x7fff;
  1364.                         if ( (c = *fmt) == '-' ) {
  1365.                                 rj = 0;
  1366.                                 c = *fmt++;
  1367.                         }
  1368.                         if ( c == '0' )
  1369.                                 fillc = '0';
  1370.                         if (c == '*') {
  1371.                                 width = getint(&args);
  1372.                                 c = *fmt++;
  1373.                         } else {
  1374.                                 c = *fmt ++;
  1375.                                 for (width = 0 ; isdigit(c);  c = *fmt++ )
  1376.                                         width = width*10 + c - '0';
  1377.                         }
  1378.                         if ( c == '.' ) {
  1379.                                 if ((c = *fmt++) == '*') {
  1380.                                         maxwidth = getint(&args);
  1381.                                         c = *fmt++;
  1382.                                 } else {
  1383.                                         for (maxwidth = 0 ; isdigit(c) ; c = *fmt++)
  1384.                                                 maxwidth = maxwidth*10 + c - '0';
  1385.                                 }
  1386.                         }
  1387.                         if (c == 'l') {
  1388.                                 c = *fmt++;
  1389.                                 value = getlong(&args);
  1390.                         } else if (c == 'd')
  1391.                                 value = getint(&args);
  1392.                         else if (c == 'e' || c == 'f' || c == 'g')
  1393.                                 dval = getdouble(&args);
  1394.                         else if (c != 's') value = getint(&args);
  1395.  
  1396.                         switch ( c ) {
  1397.                         case 'o':
  1398.                                 cp = uconvert(value, 8, s+14);
  1399.                                 break;
  1400.                         case 'd':
  1401.                                 if ( value < 0 ) {
  1402.                                         cp = convert(-value, 10, s+14);
  1403.                                         *--cp = '-';
  1404.                                 } else
  1405.                                         cp = convert(value, 10, s+14);
  1406.                                 break;
  1407.                         case 'u':
  1408.                                 cp = uconvert((val_t)(uval_t)value, 10, s+14);
  1409.                                 break;
  1410.                         case 'x':
  1411.                                 cp = uconvert(value, 16, s+14);
  1412.                                 break;
  1413.                         case 's':
  1414.                                 ap = (char * *) args;
  1415.                                 i = strlen(cp = *ap);
  1416.                                 args += sizeof(char *);
  1417.                                 goto havelen;
  1418.                         case 'e':
  1419.                         case 'f':
  1420.                       ftoa(dval, s, maxwidth==0x7fff?6:maxwidth, c=='e'?0:1);
  1421.                                 i = strlen(cp = s);
  1422.                                 maxwidth = 400;
  1423.                                 goto havelen;
  1424.  
  1425.                         case 'c':
  1426.                                 c = value;
  1427.                                 goto defcase;
  1428.  
  1429.                         default:
  1430.                                 args = oldarg;
  1431.                 defcase:
  1432.                                 *(cp = s+13) = c;
  1433.                                 break;
  1434.                         }
  1435.  
  1436.                         i = (s+14) - cp;
  1437.                 havelen:
  1438.                         if ( i > maxwidth )
  1439.                                 i = maxwidth;
  1440.  
  1441.                         if ( rj ) {
  1442.                                 while ( width-- > i )
  1443.                                         (*putsub)(fillc);
  1444.                         }
  1445.                         for ( k = 0 ; *cp && k < maxwidth ; ++k )
  1446.                                 (*putsub)(*cp++);
  1447.  
  1448.                         if ( !rj ) {
  1449.                                 while ( width-- > i )
  1450.                                         (*putsub)(' ');
  1451.                         }
  1452.                 } else
  1453.                         (*putsub)(c);
  1454.         }
  1455. }
  1456.  
  1457. static char digits[]="0123456789abcdef";
  1458.  
  1459. static char *
  1460. convert(n, base, s)
  1461. register int base; register char *s; register uval_t n;
  1462. {
  1463.         do {
  1464.                 *--s = digits[(int)(n%base)];
  1465.         } while ( (n /= base) != 0 );
  1466.         return s;
  1467. }
  1468.  
  1469. static char *
  1470. uconvert(n, base, s)
  1471. register int base; register char *s; long n;
  1472. {
  1473.         register int t;
  1474.  
  1475.         if (n < 0) {
  1476.                 t = (int)n&1;
  1477.                 n = (n>>1)&0x7fffffff;
  1478.                 *--s = digits[((int)(n%(base>>1))<<1)+t];
  1479.                 n /= base>>1;
  1480.         }
  1481.         return convert(n,base,s);
  1482. }
  1483.  
  1484.  
  1485.  
  1486. ftoa(number, buffer, maxwidth, flag)
  1487. double number; register char *buffer;
  1488. {
  1489.         register int i;
  1490.         int exp, digit, decpos, ndig;
  1491.         int zero = 0, one = 1, ten = 10;
  1492.  
  1493.         ndig = maxwidth+1;
  1494.         if (number < zero) {
  1495.                 number = -number;
  1496.                 *buffer++ = '-';
  1497.         }
  1498.         exp = 0;
  1499.         if (number > 0.0) {
  1500.                 while (number < one) {
  1501.                         number *= ten;
  1502.                         --exp;
  1503.                 }
  1504.                 while (number >= ten) {
  1505.                         number /= ten;
  1506.                         ++exp;
  1507.                 }
  1508.         }
  1509.  
  1510.         if (flag)
  1511.                 ndig += exp;
  1512.         if (ndig > 0) {
  1513.                 if ((number += round[ndig>15?15:ndig-1]) >= 10.0) {
  1514.                         number /= 10.0;
  1515.                         ++exp;
  1516.                         if (flag)
  1517.                                 ++ndig;
  1518.                 }
  1519.         }
  1520.  
  1521.         if (flag) {
  1522.                 if (exp < 0) {
  1523.                         *buffer++ = '0';
  1524.                         *buffer++ = '.';
  1525.                         for (i = exp ; ++i < 0 && maxwidth ; --maxwidth)
  1526.                                 *buffer++ = '0';
  1527.                         decpos = 0;
  1528.                 } else {
  1529.                         decpos = exp+1;
  1530.                         maxwidth += exp+1;
  1531.                 }
  1532.         } else {
  1533.                 maxwidth++;
  1534.                 decpos = 1;
  1535.         }
  1536.  
  1537.         while (maxwidth--) {
  1538.                 digit = (int)number;
  1539.                 *buffer++ = digit+'0';
  1540.                 if (decpos && --decpos == 0)
  1541.                         *buffer++ = '.';
  1542.                 number = (number - digit) * ten;
  1543.         }
  1544.         if (decpos) {
  1545.                 while (--decpos)
  1546.                         *buffer++ = '0';
  1547.                 *buffer++ = '.';
  1548.         }
  1549.  
  1550.         if (!flag) {
  1551.                 *buffer++ = 'e';
  1552.                 if (exp < 0) {
  1553.                         *buffer++ = '-';
  1554.                         exp = -exp;
  1555.                 } else
  1556.                         *buffer++ = '+';
  1557.                 if (exp >= 100) {
  1558.                         *buffer++ = exp/100 + '0';
  1559.                         exp %= 100;
  1560.                 }
  1561.                 *buffer++ = exp/10 + '0';
  1562.                 *buffer++ = exp%10 + '0';
  1563.         }
  1564.         *buffer = 0;
  1565. }
  1566.  
  1567. getint(s)
  1568. char **s;
  1569. { int *in;
  1570.   in = (int *) *s;
  1571.   (*s) += sizeof(int);
  1572.   return(*in);
  1573. }
  1574.  
  1575. long getlong(s)
  1576. char **s;
  1577. { long *lint;
  1578.   lint = (long *) *s;
  1579.   (*s) += sizeof(long);
  1580.   return(*lint);
  1581. }
  1582.  
  1583. double getdouble(s)
  1584. char **s;
  1585. { double *dval;
  1586.   dval = (double *) *s;
  1587.   (*s) += sizeof(double);
  1588.   return(*dval);
  1589. }
  1590.